; K-Base by Kouri (Kouri@ucdavis.edu)
; http://kouri.cjb.net
; This is just another asm number base converter. I made it last night because I was bored. It's pretty small, but it could
; be smaller. I could take out the "floating window" effect but then it wouldn't look so nice. :)
; Anyway, to use it, just run it from your shell. A little window will pop up that looks like this:
; +-----------------+
; |0d               |   <-- decimal
; |0                |   <-- hexadecimal
; |0                |   <-- binary
; |0                |   <-- octal
; +-----------------+
; Then it will wait for your input.

; The controls are:
; UP/DOWN    - Change the current base. The letter corresponding to the base will appear on the line that you select.
;              d = decimal, h = hexadecimal, b = binary, o = octal
; LEFT/RIGHT - Decrement/increment the number.
; 0-9, A-F   - Input a digit. Don't worry, it won't let you input digits that are not in the number base.
; DEL        - Backspace (erase the last digit).
; CLEAR      - Exit the program

; Well that's it. If you have any questions, comments, or suggestions, please e-mail me.
; Thanks to Jonah Cohen (http://jonah.ticalc.org) for helping with some optimizations, and Dan Englender
; (http://tcpa.calc.org) for helping with the 83(+) equates.

#include ion.inc
#ifdef TI83P
_savedisp = 4C7Bh
.org progstart-2
.db $BB,$6D
#else
_SaveOscreen = 4859h
BACKUP_DISP  = _SaveOscreen
.org progstart
#endif
 xor a \ jr nc,Start

.db "K-Base by Kouri",0

#define ROM_CALL(addr) bcall(addr)
DIV_HL_A    = _divhlbya
M_CHARPUT   = _vputmap
CR_KHAND    = _getcsc
CR_GRBCopy  = ionFastCopy
TEXT_MEM    = textshadow
APD_BUF     = apdram
GRAF_CURS   = pencol
CURSOR_Y    = penrow
K_DEL       = 38h
K_CLEAR     = 0Fh
K_0         = 21h
K_1         = 22h
K_2         = 1Ah
K_3         = 12h
K_4         = 23h
K_5         = 1Bh
K_6         = 13h
K_7         = 24h
K_8         = 1Ch
K_9         = 14h
K_MATH      = 2Fh
K_MATRIX    = 27h
K_PRGM      = 1Fh
K_INVERSE   = 2Eh
K_SIN       = 26h
K_COS       = 1Eh
Base        = TEXT_MEM

Start:
#ifdef TI83P
 ld hl,APD_BUF
 bcall(_savedisp)
#else
 ROM_CALL(BACKUP_DISP)		; Save display to APD_BUF
#endif
 call DrawWindow		; Draw window in APD_BUF
 ld a,(Index)
StoreBase:			; b is already 0
 ld c,a
 ld hl,Bases
 add hl,bc
 ld a,(hl)
 ld h,b
 ld l,a
 ld (Base),hl
 set textwrite,(iy+sgrflags)	; 7,(iy+14h) ; Write text to GRAPH_MEM

Main:
 ld hl,APD_BUF			; Copy APD_BUF to GRAPH_MEM
 ld de,GRAPH_MEM
 ld bc,768
 ldir
 ld de,256*19+14		; Start at (14,19)
 ld c,3				; Print 4 numbers
PrintLoop:
 push bc
 push de
 ld (GRAF_CURS),de
 ld hl,Bases
 add hl,bc
 ld c,(hl)
 ld hl,(Num)
UnpackLoop:
 ld a,c
 bcall(DIV_HL_A)
 push af
 inc b
 ld a,h
 or l \ jr nz,UnpackLoop

DispDigit:
 pop af
 add a,$90
 daa
 adc a,$40
 daa
 ROM_CALL(M_CHARPUT)
 djnz DispDigit
 ld a,3
 ld hl,Index
 ld c,(hl)
 sub c
 ld e,a
 add a,a
 add a,e
 add a,a
 add a,19
 ld hl,CURSOR_Y
 cp (hl) \ jr nz,NoCursor
 ld hl,Chars
 add hl,bc
 ld a,(hl)
 ROM_CALL(M_CHARPUT)
NoCursor:
 pop de
 pop bc
 ld a,d
 add a,6
 ld d,a
 dec c \ jp p,PrintLoop
 call CR_GRBCopy		; Refresh the screen

GetInput:
 bcall(CR_KHAND)
 cp K_CLEAR \ ret z
 ld hl,(Num)
 cp K_DEL   \ jr z,Backspace
 ld b,0
 or a  \ jr z,GetInput
 dec a \ jr z,Down
 dec a \ jr z,Left
 dec a \ jr z,Right
 dec a \ jr z,Up
 ld hl,Keys
 ld bc,(Base)
 add hl,bc
 dec hl
 cpdr \ jr nz,GetInput
 ld hl,(Num)
 ld d,h
 ld e,l
 ld a,(Base)
 ld b,a
 dec b
MulLoop:
 add hl,de \ jr c,GetInput
 djnz MulLoop
 add hl,bc
StoreNum:
 ld (Num),hl
 jp Main

Backspace:
 ld a,(Base)
 bcall(DIV_HL_A)
 jr StoreNum

Right
 inc hl
 inc hl
Left:
 dec hl
 jr StoreNum

Up:
 ld a,2
Down:
 dec a
 ld hl,Index
 add a,(hl)
 and 3
 ld (hl),a
 jp StoreBase

DrawWindow:			; Thanks to Jonah Cohen for helping me optimize this
 ld hl,APD_BUF+(18*12)+(11/8)
 call DrawBorder
 ld bc,256*25
 ld de,%0000100000100000
RectangleLoop:
 push bc
 call Clear
 pop bc
 djnz RectangleLoop
DrawBorder:
 ld c,11111111b
 ld de,%0000111111100000
Clear:
 ld a,(hl)
 and %11110000
 or d
 ld (hl),a
 ld b,8
ClearLoop:
 inc hl
 ld (hl),c
 djnz ClearLoop
 inc hl
 ld a,(hl)
 and %00111111
 or e
 ld (hl),a
 inc hl \ inc hl \ inc hl
 ret

Num:   .dw 0
Index: .db 3
Bases: .db 8, 2, 16, 10		; Stored in reverse order
Chars: .db 'o', 'b', 'h', 'd'
Keys:  .db K_0-4, K_1-4, K_2-4, K_3-4, K_4-4, K_5-4, K_6-4, K_7-4, K_8-4, K_9-4, K_MATH-4, K_MATRIX-4, K_PRGM-4, K_INVERSE-4, K_SIN-4, K_COS-4

.end
